package data;

import java.io.*;
import java.util.ArrayList;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import model.Exercise;

/**
 * 
 * Reads/Writes to the Exercises database. 
 * @author Roman Pusec, Dennis Goldfinger, Marko Bilic
 *
 */
public class BasicExerciseDao implements IDao<Exercise> {

	private String filepath;
	static final String EXERCISE = "exercise";
	static final String EXERCISES = "exercises";
	static final String NAME = "name";
	static final String EXPENDITURE = "expenditure";
	
	/**
	 * Constructor which specifies the filepath. 
	 * @param filepath The path to the database. 
	 */
	public BasicExerciseDao(String filepath)
	{
		this.filepath = filepath;
	}
	
	/**
	 * Gets all of the Exercises from the database. 
	 */
	@Override
	public ArrayList<Exercise> getAll() {

		ArrayList<Exercise> items = new ArrayList<Exercise>();
		try 
		{
			//opening xmlinputfactory
			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
			//setting up the eventReader
			InputStream in = new FileInputStream(filepath);
			XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
			// read the XML document
			Exercise basic = null;
			
			while(eventReader.hasNext())
			{
				XMLEvent event = eventReader.nextEvent();
				
				if(event.isStartElement())
				{
					StartElement startElement = event.asStartElement();
					
					if(startElement.getName().getLocalPart().equals(EXERCISE))
					{
						basic = new Exercise("", 0);
					}
					
					if(startElement.getName().getLocalPart().equals(NAME))
					{
						event = eventReader.nextEvent();
						basic.setName(event.asCharacters().getData());
						continue;
					}
					
					if(startElement.getName().getLocalPart().equals(EXPENDITURE))
					{
						event = eventReader.nextEvent();
						basic.setExpenditure(Double.parseDouble(event.asCharacters().getData()));
						continue;
					}
				}
				else if(event.isEndElement())
				{
					EndElement endElement = event.asEndElement();
					if(endElement.getName().getLocalPart().equals(EXERCISE))
					{
						items.add(basic);
					}
				}
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (XMLStreamException e) { 
			e.printStackTrace();
		}
		
		return items;
	}

	/**
	 * Writes all of the Exercises to the database. 
	 */
	@Override
	public void writeAll(ArrayList<Exercise> basicExercises) throws Exception {
		
		// create an XMLOutputFactory
	    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
	    // create XMLEventWriter
	    XMLEventWriter eventWriter = outputFactory.createXMLEventWriter(new FileOutputStream(filepath));
	    // create an EventFactory
	    XMLEventFactory eventFactory = XMLEventFactory.newInstance();
	    XMLEvent end = eventFactory.createDTD("\n");
	    XMLEvent tab = eventFactory.createDTD("\t");
	    // create and write Start Tag
	    StartDocument startDocument = eventFactory.createStartDocument();
	    eventWriter.add(startDocument);
	    
	    // create config open tag
	    eventWriter.add(end);
	    StartElement itemsStartElement = eventFactory.createStartElement("", "", EXERCISES);
	    eventWriter.add(itemsStartElement);
	    eventWriter.add(end);
	    
	    for(Exercise basic : basicExercises)
	    {
	    	StartElement singleItemStartElement = eventFactory.createStartElement("", "", EXERCISE);
	    	eventWriter.add(tab);
	    	eventWriter.add(singleItemStartElement);
	    	eventWriter.add(end);
	    	
	    	// Write the different nodes
		    createNode(eventWriter, NAME, basic.getName());
		    createNode(eventWriter, EXPENDITURE, Double.toString(basic.getExpenditure()));
		    
		    eventWriter.add(tab);
		    eventWriter.add(eventFactory.createEndElement("", "", EXERCISE));
		    eventWriter.add(end);
	    }
	    
	    eventWriter.add(eventFactory.createEndElement("", "", EXERCISES));
	    eventWriter.add(end);
	    eventWriter.add(eventFactory.createEndDocument());
	    eventWriter.close();
		
	}
	
	/**
	 * Creates a node in the XML file. 
	 * @param eventWriter The event writer. 
	 * @param name The name of the node. 
	 * @param value The value of the node. 
	 * @throws XMLStreamException 
	 */
	private void createNode(XMLEventWriter eventWriter, String name, String value) throws XMLStreamException 
	{	
	    XMLEventFactory eventFactory = XMLEventFactory.newInstance();
	    XMLEvent end = eventFactory.createDTD("\n");
	    XMLEvent tab = eventFactory.createDTD("\t\t");
	    // create Start node
	    StartElement sElement = eventFactory.createStartElement("", "", name);
	    eventWriter.add(tab);
	    eventWriter.add(sElement);
	    // create Content
	    Characters characters = eventFactory.createCharacters(value);
	    eventWriter.add(characters);
	    // create End node
	    EndElement eElement = eventFactory.createEndElement("", "", name);
	    eventWriter.add(eElement);
	    eventWriter.add(end);	
	}

}
